package com.fm.demo.service

import android.annotation.SuppressLint
import android.app.Activity
import android.app.Service
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.PixelFormat
import android.hardware.display.DisplayManager
import android.hardware.display.VirtualDisplay
import android.media.ImageReader
import android.media.projection.MediaProjection
import android.media.projection.MediaProjectionManager
import android.os.Build
import android.os.IBinder
import android.util.DisplayMetrics
import android.view.*
import com.blankj.utilcode.util.LogUtils
import com.fm.demo.R
import com.fm.demo.utils.CommonUtils
import kotlinx.coroutines.*

/**
 * @CreateData:     2019/11/1 9:33
 * @E-Mail:         709674174@qq.com
 * @Author:         lyy
 * @Description:    启动悬浮窗界面
 */
class ScreenShotFloatWindowsService : Service() {
    private var mMediaProjection: MediaProjection? = null
    private var resultData: Intent? = null
    private var mVirtualDisplay: VirtualDisplay? = null
    private var mImageReader: ImageReader? = null
    private var mWindowManager: WindowManager? = null
    private var mLayoutParams: WindowManager.LayoutParams? = null
    private var mGestureDetector: GestureDetector? = null

    private var mFloatView: ViewGroup? = null

    private var mScreenWidth: Int = 0
    private var mScreenHeight: Int = 0
    private var mScreenDensity: Int = 0

    private val mediaProjectionManager: MediaProjectionManager
        get() = getSystemService(Context.MEDIA_PROJECTION_SERVICE) as MediaProjectionManager

    override fun onCreate() {
        super.onCreate()
        createFloatView()
        createImageReader()
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        if (null != intent) {
            resultData = intent.getParcelableExtra("data")
        }
        return START_STICKY
    }

    override fun onBind(intent: Intent): IBinder? {
        return null
    }

    @SuppressLint("InflateParams")
    private fun createFloatView() {
        if (mWindowManager != null) {
            return
        }
        mGestureDetector = GestureDetector(this, FloatGestrueTouchListener())
        mLayoutParams = WindowManager.LayoutParams()
        mWindowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager
        mWindowManager?.let { it ->
            val metrics = DisplayMetrics()
            it.defaultDisplay.getMetrics(metrics)
            mScreenDensity = metrics.densityDpi
            mScreenWidth = metrics.widthPixels
            mScreenHeight = metrics.heightPixels

            mLayoutParams?.let {
                it.type = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
                } else {
                    @Suppress("DEPRECATION")
                    WindowManager.LayoutParams.TYPE_SYSTEM_ALERT
                }
                it.format = PixelFormat.RGBA_8888
                // 设置Window flag
                it.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                it.gravity = Gravity.START or Gravity.TOP
                it.x = mScreenWidth
                it.y = 100
                it.width = WindowManager.LayoutParams.WRAP_CONTENT
                it.height = WindowManager.LayoutParams.WRAP_CONTENT
            }
            mFloatView = LayoutInflater.from(this).inflate(R.layout.screen_shot_float_windows_layout, null) as ViewGroup
            mFloatView?.let {
                it.setOnTouchListener { _, event -> mGestureDetector!!.onTouchEvent(event) }
            }
            it.addView(mFloatView, mLayoutParams)
        }
    }


    private inner class FloatGestrueTouchListener : GestureDetector.OnGestureListener {
        internal var lastX: Int = 0
        internal var lastY: Int = 0
        internal var paramX: Int = 0
        internal var paramY: Int = 0

        override fun onDown(event: MotionEvent): Boolean {
            lastX = event.rawX.toInt()
            lastY = event.rawY.toInt()
            paramX = mLayoutParams!!.x
            paramY = mLayoutParams!!.y
            return true
        }

        override fun onShowPress(e: MotionEvent) {

        }

        override fun onSingleTapUp(e: MotionEvent): Boolean {
            startScreenShot()
            return true
        }

        override fun onScroll(e1: MotionEvent, e2: MotionEvent, distanceX: Float, distanceY: Float): Boolean {
            val dx = e2.rawX.toInt() - lastX
            val dy = e2.rawY.toInt() - lastY
            mLayoutParams!!.x = paramX + dx
            mLayoutParams!!.y = paramY + dy
            // 更新悬浮窗位置
            mWindowManager!!.updateViewLayout(mFloatView, mLayoutParams)
            return true
        }

        override fun onLongPress(e: MotionEvent) {

        }

        override fun onFling(e1: MotionEvent, e2: MotionEvent, velocityX: Float, velocityY: Float): Boolean {
            return false
        }
    }


    private fun startScreenShot() {
        mFloatView?.visibility = View.GONE
        GlobalScope.launch {
            LogUtils.e("test thread : ${Thread.currentThread()}")
            delay(5)
            startVirtual()
            delay(25)
            startCapture()
        }
    }


    private fun createImageReader() {
        mImageReader = ImageReader.newInstance(mScreenWidth, mScreenHeight, PixelFormat.RGBA_8888, 1)
    }

    private fun startVirtual() {
        if (mMediaProjection != null) {
            virtualDisplay()
        } else {
            setUpMediaProjection()
            virtualDisplay()
        }
    }

    private fun setUpMediaProjection() {
        if (resultData == null) {
            val intent = Intent(Intent.ACTION_MAIN)
            intent.addCategory(Intent.CATEGORY_LAUNCHER)
            startActivity(intent)
        } else {
            mMediaProjection = mediaProjectionManager.getMediaProjection(Activity.RESULT_OK, resultData!!)
        }
    }

    private fun virtualDisplay() {
        mVirtualDisplay = mMediaProjection!!.createVirtualDisplay(
            "screen-mirror",
            mScreenWidth, mScreenHeight, mScreenDensity, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
            mImageReader!!.surface, null, null
        )
    }

    private fun startCapture() {
        val image = mImageReader?.acquireLatestImage()
        if (image == null) {
            startScreenShot()
        } else {
            GlobalScope.launch(Dispatchers.Main) {
                LogUtils.e("test1 thread : ${Thread.currentThread()}")
                val result = async(Dispatchers.IO) {
                    LogUtils.e("test2 thread : ${Thread.currentThread()}")
                    val width = image.width
                    val height = image.height
                    val planes = image.planes
                    val buffer = planes[0].buffer
                    //每个像素的间距
                    val pixelStride = planes[0].pixelStride
                    //总的间距
                    val rowStride = planes[0].rowStride
                    val rowPadding = rowStride - pixelStride * width
                    val bitmap: Bitmap? = Bitmap.createBitmap(width + rowPadding / pixelStride, height, Bitmap.Config.ARGB_8888)
                    bitmap?.let {
                        it.copyPixelsFromBuffer(buffer)
                        val tempBitmap = Bitmap.createBitmap(it, 0, 0, width, height)
                        return@async CommonUtils.saveImage(application, tempBitmap)
                    }
                    false
                }.await()
                LogUtils.e("screen shot and save ,send to system : $result")
                image.close()
                mFloatView?.let {
                    it.visibility = View.VISIBLE
                }
            }
        }
    }


    private fun tearDownMediaProjection() {
        if (mMediaProjection != null) {
            mMediaProjection?.stop()
            mMediaProjection = null
        }
    }

    private fun stopVirtual() {
        if (mVirtualDisplay == null) {
            return
        }
        mVirtualDisplay?.release()
        mVirtualDisplay = null
    }

    override fun onDestroy() {
        // to remove mFloatLayout from windowManager
        super.onDestroy()
        if (mFloatView != null) {
            mWindowManager?.removeView(mFloatView)
        }
        stopVirtual()
        tearDownMediaProjection()
    }


}
